#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>        /* Definition of uint64_t */
#include<chrono>
#include<iostream>
using namespace std;

#define handle_error(msg) \
       do { perror(msg); exit(EXIT_FAILURE); } while (0)

static void
print_elapsed_time(void)
{
    static auto start = chrono::system_clock::now();
    auto end = chrono::system_clock::now();
    auto dura = chrono::duration_cast<chrono::seconds>(end-start);
    cout<<"seconds:"<<dura.count()<<" ";
}

int
main(int argc, char *argv[])
{
   struct itimerspec new_value;
   int max_exp, fd;
   struct timespec now;
   uint64_t exp, tot_exp;
   ssize_t s;

   if ((argc != 2) && (argc != 4)) {
       fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
               argv[0]);
       exit(EXIT_FAILURE);
   }

   if (clock_gettime(CLOCK_REALTIME, &now) == -1)
       handle_error("clock_gettime");

   /* Create a CLOCK_REALTIME absolute timer with initial
      expiration and interval as specified in command line */

   new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
   new_value.it_value.tv_nsec = now.tv_nsec;
   if (argc == 2) {
       new_value.it_interval.tv_sec = 0;
       max_exp = 1;
   } else {
       new_value.it_interval.tv_sec = atoi(argv[2]);
       max_exp = atoi(argv[3]);
   }
   new_value.it_interval.tv_nsec = 0;

   fd = timerfd_create(CLOCK_REALTIME, 0);
   if (fd == -1)
       handle_error("timerfd_create");

   if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
       handle_error("timerfd_settime");

   print_elapsed_time();
   printf("timer started\n");

   for (tot_exp = 0; tot_exp < max_exp;) {
       s = read(fd, &exp, sizeof(uint64_t));
       if (s != sizeof(uint64_t))
           handle_error("read");

       tot_exp += exp;
       print_elapsed_time();
       printf("read: %llu; total=%llu\n",
               (unsigned long long) exp,
               (unsigned long long) tot_exp);
   }

   exit(EXIT_SUCCESS);
}